#include "config.h"
#include "../../../vcd-common-api/vcd-common.h"
#include "../../vcd-message-dialog.h"
#include "vcd-sys-upgrade.h"
#include "../vcd-setting-window.h"

char g_now_version[25];
char g_new_version[25];

client_upgrade *g_client_upgrade_context = NULL;

/* 获取当前版本信息 */
static void get_version(void);

/*创建上下文*/
static client_upgrade* create_client_upgrade_context(void);
/*检查新更新按钮回调*/
static void cb_check_new_version_task(GtkWidget *btn);
/*开始检查是否有新更新*/
static gboolean check_new_version(gpointer btn);
/*开始检查新更新的线程*/
static void start_check_new_version_thread(GtkWidget *btn);
/*设置为正在检查新更新的状态*/
static void start_check_new_version_status(GtkWidget *btn);
/*设置为已经结束检查新更新的状态*/
static void stop_check_new_version_status(GtkWidget *btn);


/*提示是否进行更新的窗口*/
static void cb_upgrade_buttonAsk(void);
/*开启更新线程*/
static void start_do_upgrade_thread(gpointer p);
/*实际更新！*/
static void deal_with_upgrade(void);

/*检查是否已经升级过，或者管理平台已经对此盒子进行过更新，但是盒子没重启*/
static gboolean check_if_upgrade_complete(void);
/*重启*/
static void cb_reboot_system(gpointer s);
/*提示重启更新客户端*/
static void messagebox_reboot_to_upgrade(gpointer s);

void get_version(void)
{
    const char* ver = PACKAGE_VERSION;
    M_DEBUG("now version full = %s", ver);
    const char *p = strstr(ver, "-");

    int t = 0;
    int cp_len = sizeof(g_now_version);
    if (p) {
        t = p - ver;
    } else {
        t = strlen(ver);
    }

    if (t < cp_len) {
        cp_len = t;
    }

    memset(g_now_version, 0, sizeof(g_now_version));
    memcpy(g_now_version, ver, cp_len);

    //the last is '\0'
    g_now_version[sizeof(g_now_version) - 1] = 0;
    M_DEBUG("now version = %s", g_now_version);
}

static void deal_with_upgrade(void)
{
    system("dnf upgrade spice-glib spice-gtk3 spice-gtk-tools -y");
}

static void start_do_upgrade_thread(gpointer p)
{
    client_upgrade *client_upgrade_context = g_client_upgrade_context;

    if (!client_upgrade_context) {
        M_DEBUG("client_upgrade_context = NULL");
        return;
    }

    client_upgrade_context->thread_do_upgrade = g_thread_new("deal_upgrade", (GThreadFunc)deal_with_upgrade, NULL);
    if (client_upgrade_context->thread_do_upgrade) {
        message_box("更新任务已于后台执行");
        M_DEBUG("start upgrade!!!");  
    }
}

static void cb_upgrade_buttonAsk(void)
{
    message_diag_context *t = g_malloc0(sizeof(message_diag_context));
    g_return_if_fail(t != NULL);
    t->btn_yes = start_do_upgrade_thread;
    t->btn_no = NULL;
    t->info = "发现新版本,是否进行升级？";
    t->user_data = NULL;
    vcd_message_dialog(t);
    g_free(t);
    t = NULL;
}

static void start_check_new_version_status(GtkWidget *btn)
{
    client_upgrade *client_upgrade_context = g_client_upgrade_context;

    if (!client_upgrade_context) {
        M_DEBUG("client_upgrade_context = NULL");
        return;
    }

    client_upgrade_context->check_new_version_flag = TRUE;
    gtk_button_set_label((GtkButton *)btn, "取消...");
    M_DEBUG("start check new version");
}

static void stop_check_new_version_status(GtkWidget *btn)
{
    client_upgrade *client_upgrade_context = g_client_upgrade_context;

    if (!client_upgrade_context) {
        M_DEBUG("client_upgrade_context = NULL");
        return;
    }

    client_upgrade_context->check_new_version_flag = FALSE;
    gtk_button_set_label((GtkButton *)btn, "检测新版本");
    M_DEBUG("stop check new version");
}

static gboolean check_new_version(gpointer btn)
{
    //这两句话如果写的话有可能kill的时候没到dnf check-upgrade所以kill失败之后g_thread_join卡死
    system("dnf repolist");
    system("dnf clean all");
    
    client_upgrade *client_upgrade_context = g_client_upgrade_context;
    
    size_t si = 0;
    char* tmp_new_version = exe_command("dnf check-upgrade | grep spice-gtk-tools | awk '{print $2}' | cut -d '.' -f 1,2", &si);
    
    /*表示提前结束了这个进程有人按了结束按钮*/
    if (!client_upgrade_context->check_new_version_flag) {
        SAFE_FREE(tmp_new_version);
        return FALSE;
    }

    gdk_threads_add_idle((GSourceFunc)stop_check_new_version_status, btn);

    if (tmp_new_version == NULL) {
        /*其实这边如果是rpm失败也是走到这里所以一旦rpm命令出现问题这里会一直显示已经更新到最新版本*/
        /*如果这里是正常结束的话，退出设置的时候也会杀一次进程，但是找不到dnf进程*/
        gdk_threads_add_idle((GSourceFunc)message_box, (gpointer)"\n  已升级为最新版本！  \n");
        M_DEBUG("dnf check-upgrade return new_version = NULL");
        return FALSE;
    } else {
        M_DEBUG("dnf check-upgrade return new_version = %s", tmp_new_version);
        strncpy(g_new_version, tmp_new_version, 25);
        gdk_threads_add_idle((GSourceFunc)cb_upgrade_buttonAsk, NULL);
    }
    SAFE_FREE(tmp_new_version);
    return TRUE;
}

static void start_check_new_version_thread(GtkWidget *btn)
{
    client_upgrade *client_upgrade_context = g_client_upgrade_context;

    if (!client_upgrade_context) {
        M_DEBUG("client_upgrade_context = NULL");
        return;
    }

    client_upgrade_context->thread_check_new_version = g_thread_new("check_version", (GThreadFunc)check_new_version, (gpointer)btn);
    if (client_upgrade_context->thread_check_new_version)
        start_check_new_version_status(btn);
}

/*退出系统设置时需要关闭检查，并释放线程,在系统设置关闭的时候会调用*/
void stop_check_new_version_thread(void)
{
    client_upgrade *client_upgrade_context = g_client_upgrade_context;

    if (!client_upgrade_context) {
        M_DEBUG("client_upgrade_context = NULL");
        return;
    }

    stop_check_new_version_status(client_upgrade_context->btn);

    M_DEBUG("killall -9 dnf");
    //跑三次是为了防止dnf repolist dnf clena all 正在跑，之后check-upgrade没杀掉，导致join卡死
    system("killall -9 dnf");
    system("killall -9 dnf");
    system("killall -9 dnf");
    g_thread_join(client_upgrade_context->thread_check_new_version);
    client_upgrade_context->thread_check_new_version = NULL;

    G_SAFE_FREE(g_client_upgrade_context);
}

static client_upgrade* create_client_upgrade_context(void)
{
    if (g_client_upgrade_context) {
        M_DEBUG("g_client_upgrade_context != NULL");
        return g_client_upgrade_context;
    }

    client_upgrade *client_upgrade_context = (client_upgrade *)g_malloc0(sizeof(client_upgrade));

    memset(g_new_version, 0, sizeof(g_new_version));

    client_upgrade_context->thread_check_new_version = NULL;
    client_upgrade_context->check_new_version_flag = FALSE;
    client_upgrade_context->thread_do_upgrade = NULL;

    return client_upgrade_context;
}

static gboolean check_if_upgrade_complete(void) 
{
    M_DEBUG("g_now_version = %s\n", g_now_version);
    size_t si = 0;
    char* tmp_new_version = exe_command("rpm -q spice-gtk-tools  |cut -d- -f 4,5|cut -d. -f 1,2|sed 's/-/./'", &si);
    M_DEBUG("rpm -q spice-gtk-tools = %s\n", tmp_new_version);

    if (strcmp(g_now_version, tmp_new_version) == 0) {
        M_DEBUG("tmp_new_version == g_now_version");
        G_SAFE_FREE(tmp_new_version);
        return FALSE;
    }
    M_DEBUG("tmp_new_version(rpm -q spice-gtk-tools) != g_now_version(spicy --version)");
    return TRUE;
}

static void cb_reboot_system(gpointer s)
{
    system("reboot");
}

static void messagebox_reboot_to_upgrade(gpointer s)
{
    message_diag_context *t = g_malloc0(sizeof(message_diag_context));
    g_return_if_fail(t != NULL);
    t->btn_yes = cb_reboot_system;
    t->btn_no = NULL;
    t->info = "您的客户端已更新完成，是否重启以激活最新版本？";
    t->user_data = s;
    vcd_message_dialog(t);
    g_free(t);
    t = NULL;
}

static void cb_check_new_version_task(GtkWidget *btn)
{
    /*进行新版本检测之前先检测一下当前版本是否已经是落后版本，本地是否已经进行过更新了，
      用当前的PACKAGE_VERSION版本和rpm -q|grep spice-gtk-tools版本进行比较是否一致*/
    if (check_if_upgrade_complete()) {
        
        messagebox_reboot_to_upgrade(NULL);
        M_DEBUG("reboot to use new version client");
        return;
    }
    
    /*创建更新任务上下文*/
    client_upgrade *client_upgrade_context = create_client_upgrade_context();
    g_client_upgrade_context = client_upgrade_context;

    g_client_upgrade_context->btn = btn;
    
    if (g_client_upgrade_context) {
        if (!client_upgrade_context->check_new_version_flag)
            start_check_new_version_thread(btn);
        else
            stop_check_new_version_thread();
    } else {
        M_DEBUG("create client_upgrade_context error");
    }
}

GtkWidget* get_upgrade_setting_fix(void)
{
    GtkWidget *fix_upgrade = gtk_fixed_new();

    get_version();

    GtkWidget *btn_upgrade = gtk_button_new_with_label("检查新版本");
    gtk_button_set_relief(GTK_BUTTON(btn_upgrade), GTK_RELIEF_NONE);
    gtk_widget_set_size_request(btn_upgrade, 120, 20);
#ifdef __linux__
    g_signal_connect_swapped(G_OBJECT(btn_upgrade), "clicked", G_CALLBACK(cb_check_new_version_task), btn_upgrade);
#endif
    set_css(btn_upgrade, "button{ color:white;"
                                                "background:rgb(53,126,169);"
                                                "border:1px solid rgb(40,94,142);"
                                                "border-radius:0px}");
    set_css(btn_upgrade, "button:hover{border-radius:0px;background: #3070a9}");
    gtk_fixed_put((GtkFixed *)fix_upgrade, btn_upgrade, 425, 325);

    GtkWidget *label_pic = gtk_label_new(NULL);
    gtk_widget_set_size_request(label_pic, 460, 50);
    set_img(label_pic, "label", "loginwindow.png");
    gtk_fixed_put((GtkFixed *)fix_upgrade, label_pic, 55,  40);

    char full_version_string[500] = {0};
    snprintf(full_version_string, sizeof(full_version_string),
             "名称  :   云桌面客户端\n"
             "版本  :   %s\n"
             "概述  :   虚拟化远程连接\n"
             "网址  :   www.verycloud.cn\n"
             "许可  :   GPLv2+\n"
             "描述  :   云端网络云桌面提供了一个用户界面来连接远程虚拟\n"
             "             机，它使用了SPICE或者RDP协议来实时更新远程虚\n"
             "             拟机的状态并可在当前显示器上控制虚拟机。\n",
             PACKAGE_VERSION);

    GtkWidget *label_version = gtk_label_new(full_version_string);
    gtk_fixed_put((GtkFixed *)fix_upgrade, label_version, 105, 143);

    return fix_upgrade;
}
